
/*******************************************************************************
 * The code below this comment is integral part of the project "Jelliphy".
 * 
 * "Jelliphy" is a project created by: 
 * Dispage - Patrizio Gelosi
 * Via A. De Gasperi 91 
 * P. Potenza Picena (MC) - Italy
 * 
 * (Hereby referred to as "DISPAGE")
 * 
 * Copyright (c) 2011 DISPAGE.
 * 
 * @Released on: 02-06-2011
 * @Version: 1.0.00
 * @Build: 1109
 * @Site: http://www.dispage.com
 * @Contacts: http://www.dispage.com/contacts
 * 
 * The contents of this file are released under the GNU General Public License
 * version 3 as published by the Free Software Foundation that can be found at
 * the address "http://opensource.org/licenses/gpl-3.0.html". If the license
 * cannot be found, write to the Free Software Foundation, Inc., 51 Franklin
 * Street, Fifth Floor, Boston, MA 02110-1301 USA.
 * 
 * You may not use the present file except in compliance with the License.
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
 * for the specific language governing rights and limitations under the
 * License.
 * 
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU General Public License version 3.
 * 
 * In accordance with Section 7(b) of the GNU General Public License version 3,
 * these Appropriate Legal Notices must retain the display of the "Powered by
 * Dispage" logo. If the display of the logo is not reasonably feasible for
 * technical reasons, the Appropriate Legal Notices must display the words
 * "Powered by Dispage".
 * 
 ******************************************************************************/

var MGMV = new function () {

	var that = this,
		
		strictCompTags = ['tr'],
		strictChildTags = ['td', 'th', 'li'],
		strictTags = [],
		noDroppableTags = 'HTML,BODY,HEAD,LINK,META,SCRIPT,TITLE,STYLE',

		flyingOver = 0,
		dropDelay = 50,
		isStrict, isStrictComp, elDepth,
		staticClone, cursorClone, $targetElement, dropElem, targetTags,
		bckM9t, isCutting, isDragging = false,
		oldDim = null,


		editCallbacks = {

			newCallback : function () {

				if (MGD.transforms.length) {
					MGDial.confirm(MGLang.confirms.load_overwrite, MGD.restoreOriginal);
				}
				else {
					MGDial.warning(MGLang.infos.new_empty, {type: 'Info'});
				}
				return -1;
			},

			cutCallback : function () {

				editCallbacks.copyCallback();

				isCutting = true;
			},

			copyCallback : function () {

				if (!MGD.lcGueSel.selectors[0]) return;

				isCutting = false;

				JlQ('#mg-cursor-copying').remove();
				
				JlQ('#mg-cursor').clone().addClass('mg-editph')
					.attr('id', 'mg-cursor-copying')
					.removeClass('mg-cursor-selected')
					.html('')
					.click(clearSelection)
					.appendTo('body');

				that.pasteElementSel = MGUtils.text2SQString(MGD.lcGueSel.selectors[0][0]);

				JlQ('.mg-items-paste').removeClass('mg-item-disabled');

				MGP.toggleElementSelection();
			},

			pasteinsideCallback : function () {

				pasteElement('append');

				MGD.selectElement(MGD.$lastCalled.children().last().get(0));
			},

			pastebeforeCallback : function () {

				pasteElement('before');

				MGD.selectElement(MGD.$lastCalled.prev().get(0));
			},

			pasteafterCallback : function () {

				pasteElement('after');

				MGD.selectElement(MGD.$lastCalled.next().get(0));
			},

			pastereplaceCallback : function () {

				pasteElement('replaceWith');

				MGD.selectElement(MGD.lastCalled);
			},

			deleteCallback : function () {

				MGED.deleteElement();
			},

			undoCallback : function () {

				MGD.trsfUndo();
			},

			redoCallback : function () {

				MGD.trsfRedo();
			}
		},
		
		getAddingHTML = function () {

			var html2Add = MGD.$lastCalled.outerHTML();

			if (JlQ.browser.msie) html2Add = MGUtils.text2SQString(html2Add);
			html2Add = html2Add.replace(/\ssrc=(?:\"|\\\')(?!https?:\/\/)|:\s*url\s*\(/ig, '$&\' + MGAddPath + \'');

			return html2Add;
		},
		
		getToAddIcons = function ($el) {

			var w = $el.width(),
				h = $el.height();

			return  (w >= 80 || h >= 40) && !(JlQ.browser.msie && (w < 45 || h < 18));
		},
		
		pasteElement = function (api) {

			var map = isCutting ? {api: 'remove', action : 'cut-elem'} : {api: 'clone', action : 'copy-elem'},
				attrAction = '',
				copyM9t = JlQ(that.pasteElementSel + ':not(.mg-cursor-clone)').attr('m9t'),
				copiedM9t, action;

			if (isCutting) {
				if (!copyM9t) copyM9t = MGD.getNextM9T();
				attrAction = '.attr("m9t", "' + copyM9t + '")';
				MGD.addTransform(api + "(JlQ('" + that.pasteElementSel + "')." + map.api + "()" + attrAction + ")", map.action, null, null, null, copyM9t);
			}
			else {
				if (copyM9t) {
					copiedM9t = MGD.getNextM9T();
				}
				else {
					copyM9t = MGD.getNextM9T();
					action = 'attr("m9t", "' + copyM9t + '")';
					MGD.addTransform(action, 'm9tize-elem', "JlQ('"+that.pasteElementSel+"')." + action, null, null, copyM9t);
					copiedM9t = MGUtils.add1Digit(copyM9t);
				}
				attrAction = '.attr("m9t", "' + copiedM9t + '")';
				MGD.addTransform(api + "(JlQ('[m9t=" + copyM9t + "]')." + map.api + "()" + attrAction + ")", map.action);
				if (api == 'replaceWith') {
					MGD.updateLastCalled("JlQ('[m9t=" + copiedM9t + "]')");
				}
				makeDroppable(eval('MGD.$lastCalled.'+ MGD.undoAddMap[api]), true);
			}
			if (isCutting) {
				JlQ('#mg-cursor-copying').remove();
			}
		},

		clearSelection = function () {

			that.pasteElementSel = '';

			JlQ('#mg-cursor-copying').remove();

			that.toggleEditMenu();
		},

		startResizeCursor = function (event, ui) {

			that.resizeClone = MGD.$lastCalled.clone(true);
			oldDim = {width: ui.originalElement.width(), height: ui.originalElement.height()};
		},

		stopResizeCursor = function (event, ui) {

			var los = MGD.$lastCalled.offset(),
				cos = ui.position,
				s = ui.size,
				w = parseInt(MGD.$lastCalled.width()),
				h = parseInt(MGD.$lastCalled.height());

			if (parseInt(los.top) != cos.top || parseInt(los.left) != cos.left) {
				ui.element.offset(los);
			}
			if (w != s.width) {
				ui.element.width(w);
			}
			if (h != s.height) {
				ui.element.height(h);
			}
			MGD.addTransform("css({width: '"+s.width + "px', height: '"+s.height + "px'})", 'resize-elem');

			MGP.characterizeElement(MGD.$lastCalled, true);

			JlQ('#mg-cursor-patch').css(JlQ('#mg-cursor-panel').offset());
		},

		startDragCursor = function (ev, ui) {

			if (!MGD.lastCalled) return false;

			if (JlQ('iframe', MGD.$lastCalled.parent()).length) {
				MGDial.warning(MGLang.warnings.no_drag_element);
				return false;
			}
			JlQ('#mg-cursor').addClass('mg-placeholder').removeClass('mg-cursor-selected');

			isDragging = true;

			if (MGP.currentMode == 'Add') {
//				refreshElem2Add();
				//MGD.updateNewLastCalled();
				staticClone = MGD.$lastCalled.clone().addClass('mg-whereto-element');
//				cursorClone = MGD.$lastCalled.clone().addClass('mg-cursor-clone').after('<div id="mg-cursor-denied" class="mg-hidden"></div>');
				JlQ('.mg-newel-cont.mg-button-down').last().append('<div id="mg-cursor-denied" class="mg-hidden"></div>');
			}
			else {
				if (cursorClone.attr('disabled')) {
					cursorClone.removeAttr('disabled');
				}
				JlQ('#mg-cursor.mg-cursor-selected')
					.append(cursorClone)
					.append('<div id="mg-cursor-denied" class="mg-hidden"></div>');
				
				if (JlQ.browser.msie) {
					JlQ('#mg-cursor.mg-cursor-selected').cssImportant('filter', '', true);
				}	
			}
		},

		dropOutCursor = function (ev, ui) {

			if (!isStrict || ui && ui.draggable[0] != dropElem) return;

			JlQ('.mg-whereto-element').remove();
			JlQ('#mg-cursor.mg-cursor-selected').cssImportant('background-color', '#F07D00');
			JlQ('#mg-cursor-denied').removeClass('mg-hidden');
		},

		dropOverCursor = function (ev, ui) {

			if (!isStrict || ui.draggable[0] != dropElem) return;

			if (flyingOver) clearTimeout(flyingOver);

			flyingOver = setTimeout( function () {
				
				var $tgEl = JlQ(targetTags+'.mg-target-element'),
					best, tgTag;

				if ($tgEl.length > 1) {
					$tgEl.each(function () {
						var dp = JlQ(this).parents().length,
							dist = Math.abs(dp - elDepth);
						if (best == null || dist < best.dist || dist == best.dist && dp > elDepth) {
							best = {dist: dist, el: this};
						}
					});
					$tgEl.filter(function () {
						return (this != best.el);
					}).removeClass('mg-target-element');
				}			
				$targetElement = JlQ(targetTags+'.mg-target-element');

				if ($targetElement.length && !$targetElement.parents('.mg-nohighlight').length) {

					JlQ('#mg-cursor.mg-cursor-selected').cssImportant('background-color', '#AAFFAA');
					JlQ('#mg-cursor-denied').addClass('mg-hidden');

					tgTag = $targetElement.get(0).tagName.toLowerCase();

					if (JlQ.inArray(tgTag, strictChildTags) == -1 || tgTag == staticClone.get(0).tagName.toLowerCase()) {
						if (!$targetElement.prev('.mg-whereto-element').length) {
							JlQ('.mg-whereto-element').remove();
							$targetElement[MGOP.prefs.insert_moving](staticClone);
						}
					}
					else {
						if (!$targetElement.children('.mg-whereto-element').length) {
							JlQ('.mg-whereto-element').remove();
							$targetElement.append(staticClone);
						}
					}
				}
			}, dropDelay);
		},

		dropCursor = function (ev, ui) {

			if (!isStrict || ui.draggable[0] != dropElem) return;

			if (!JlQ('.mg-whereto-element').length) {
				endDragCursor();
				return true;
			}
			var $addedEl, html2Add, api, srTag, seekM9t,
				
				tgGueSel = new MGGueSel,
					
				exchangeEls = function (st, tt) {

					tgGueSel.updateElSelector();
					MGD.updateLastCalled("JlQ('"+ MGUtils.text2SQString(tgGueSel.selectors[0][0])+ "')");

					return (isStrictComp || JlQ.inArray(st, strictChildTags) == -1 || st == tt) ? MGOP.prefs.insert_moving : 'append';
				};

			dropOutCursor();

			$targetElement.removeClass('mg-target-element');

			tgGueSel.populateSelectorList($targetElement);

			srTag = MGD.lastCalled.tagName.toLowerCase();

			if (MGP.currentMode == 'Add') {
				MGD.syncDefDisplay();
				html2Add = getAddingHTML();
				/*
				tgGueSel.updateElSelector();
				MGD.updateLastCalled("JlQ('"+ MGUtils.text2SQString(tgGueSel.selectors[0][0])+ "')");
				tgTag = MGD.lastCalled.tagName.toLowerCase();
				api = (isStrictComp || JlQ.inArray(tgTag, strictChildTags) == -1 || srTag == tgTag) ? 'before' : 'append';
				*/
				api = exchangeEls(MGD.lastCalled.tagName.toLowerCase(), srTag);

				MGD.addTransform(api + "('" + html2Add + "')", 'add-elem');
				makeDroppable(eval('MGD.$lastCalled.'+ MGD.undoAddMap[api]), true);
				endDragCursor();
			}
			else {
				isCutting = true;
				that.pasteElementSel = MGUtils.text2SQString(JlQ('#mg-element-selector').val());
				if ($targetElement.get(0) == MGD.lastCalled) return;
				/*
				tgGueSel.updateElSelector();
				MGD.updateLastCalled("JlQ('"+ MGUtils.text2SQString(tgGueSel.selectors[0][0])+ "')");
				api = (isStrictComp || JlQ.inArray(srTag, strictChildTags) == -1 || srTag == $targetElement.get(0).tagName.toLowerCase()) ? 'before' : 'append';
				*/
				api = exchangeEls(srTag, $targetElement.get(0).tagName.toLowerCase());

				pasteElement(api);
				$addedEl = eval('MGD.$lastCalled.'+ MGD.undoAddMap[api]);
				if ($addedEl.hasClass('mg-cursor-clone')) {
					if (seekM9t = $addedEl.attr('m9t')) {
						$addedEl = JlQ('[m9t=' + seekM9t + ']:not(.mg-cursor-clone)');
					}
					if (!seekM9t || !$addedEl.length) {
						$addedEl = eval('$addedEl.'+ MGD.undoAddMap[api]);
					}
				}
				makeDroppable($addedEl, true);
				endDragCursor($addedEl);
			}
		},

		stopDragCursor = function (ev, ui) {

			var html2Add, elOffset;

			if (MGP.currentMode == 'Add') {

				elOffset = ui.offset;

				if (MGD.$lastCalled.css('position') == 'absolute') {
					elOffset.top += JlQ(document).scrollTop();
					elOffset.left += JlQ(document).scrollLeft();
				}
				MGD.syncDefDisplay();
				MGD.$lastCalled.addClass('mg-added-absolute-element');
				MGD.$lastCalled.offset({top: elOffset.top , left: elOffset.left});
				html2Add = getAddingHTML();
				MGD.lcGueSel.updateElSelector([['body', 'body']]);
				MGD.updateLastCalled("JlQ('body')");
				MGD.addTransform("append('" + html2Add + "')", 'add-elem');
				makeDroppable(MGD.$lastCalled.children().last(), true);
			}
			else {
				MGD.addTransform("offset({top: '" + Math.round(ui.position.top) + "', left: '" +  Math.round(ui.position.left) + "'})", 'change-prop');
			}
			endDragCursor();
		},

		endDragCursor = function ($el) {

			if (!isDragging) return;

			isDragging = false;
			
			JlQ('.mg-cursor-clone').remove();

			JlQ('.mg-target-element').removeClass('mg-target-element');
			JlQ('#mg-cursor').removeClass('mg-placeholder').addClass('mg-cursor-selected');

			if (MGP.currentMode == 'Add') {
				MGD.updateLastCalled(staticClone.removeClass('mg-whereto-element'));
			}
			else {
				if (!$el || !$el.length || $el.handler) {
					$el = MGD.$lastCalled;
					MGP.showElement($el, 'mg-cursor');
				}
				else {
					MGP.shadowElement($el.get(0));
					MGD.updateAESelector();
				}
				JlQ('#mg-cursor-patch').css(JlQ('#mg-cursor-panel').offset());
			}
			//dropElem = null;
		},
			
		makeDroppable = function ($el, descendants) {

			if (descendants) {
				$el = $el.add($el.find('*'));
			}
			$el.droppable({
				hoverClass: 'mg-target-element',
				tolerance: 'pointer',
				addClasses: false,
				scope: 'visual-elements',
				over: dropOverCursor,
				out: dropOutCursor,
				drop: dropCursor
			});
		},
			
		keydownEditArea = function (ev) {

			var keyCode = ev.keyCode || ev.which;

			if (keyCode == 27) {
				JlQ('#mg-quickedit').addClass('mg-hidden');
			}
		},
			
		focusEditArea = function () {

			JlQ('#mg-quickedit textarea').focus();
		},
			
		dblClickCursor = function () {

			var $qe = JlQ('#mg-quickedit'),
				$cur, offset, $textarea, html;

			if (!$qe.hasClass('mg-hidden')) {
				$qe.addClass('mg-hidden');
				return;
			}
			bckM9t = MGD.getCurrentM9T();
			$cur = JlQ('#mg-cursor');
			offset = $cur.offset();
			$textarea = JlQ('#mg-quickedit textarea');
			html = MGD.$lastCalled.clone().mgAddM9T().outerHTML();

			$qe.css({
				top: offset.top +  $cur.height() + 5,
				left: offset.left,
				width: Math.min(800, Math.max(300, $cur.width()))
			})
				.removeClass('mg-hidden');

			$textarea.val(html)
				.css({
					width: '100%',
					maxHeight: '500px',
					height: 'auto'
				})
				.keydown(keydownEditArea)
				.elastic();

			MGP.bringToFront($qe);

			if (!JlQ('#mg-current-element').html()) {
				MGP.characterizeElement(MGD.$lastCalled, true);
			}
			focusEditArea();
		},

		saveQuickEdit = function () {

			MGD.addTransform("replaceWith('" + MGUtils.text2SQString(JlQ('#mg-quickedit textarea').val()) + "')", 'change-elem');
			JlQ('#mg-quickedit').addClass('mg-hidden');

			MGD.selectElement(JlQ('[m9t='+MGD.getCurrentM9T()+']').get(0));
		},

		helperFunction = function () {

			var $clone = JlQ(this).clone();
			
			JlQ('.mg-add-removable', $clone).remove();
			
			return $clone;
		},
			
		cancelQuickEdit = function () {

			MGD.setCurrentM9T(bckM9t);
			JlQ('#mg-quickedit').addClass('mg-hidden');
		},
			
		clickMenuEdit = function () {

			var $this = JlQ(this);
			
			if ($this.hasClass('mg-item-disabled')) return;

			if ($this.hasClass('mg-item-change') && !MGD.elIsSelected) {
				MGDial.warning(MGLang.warnings.edit_select_element);
				return;
			}
			eval('editCallbacks.' + $this.children('a').attr('item') + 'Callback()');
		},

		activateEditMenu = function () {

			JlQ('#mg-cursor').removeClass('mg-editph');
			JlQ('.mg-items-paste').addClass('mg-item-disabled');
		},
	
		toggleEditMenu = function () {

			if (MGD.elIsSelected) {
				JlQ('.mg-item-cur-sel').removeClass('mg-item-disabled');
				JlQ('.mg-items-paste').toggleClass('mg-item-disabled', that.pasteElementSel == '');
			}
			else {
				JlQ('.mg-item-change').addClass('mg-item-disabled');
			}
		};

	that.abPosEquiv = ['absolute', 'fixed'];
	that.pasteElementSel = '';
	that.resizeClone = null;

	that.initDragDrop = function ($cur) {

		var $curPanel = JlQ('#mg-cursor-panel', $cur).length ? JlQ('#mg-cursor-panel', $cur) : $cur,
			addingMode = MGP.currentMode == 'Add',
			curClass = addingMode ? 'mg-cursor-add-handler' : 'mg-images-black JLui-icon-arrow-4',
			$el, tag, stopDrag, revert;
	
		JlQ('.mg-cursor-buttons').remove();

		if (addingMode || getToAddIcons($cur)) {
			$curPanel.append('<div id="mg-cursor-handler" class="mg-add-removable mg-images mg-cursor-buttons ' + curClass + '"></div>');
		}
		$el = MGD.$lastCalled;
		tag = $el.get(0).tagName.toLowerCase();
		isStrict = JlQ.inArray($el.css('position'), that.abPosEquiv) == -1;
/*
		if ($cur.height() < 12) {
			$cur.height(12);
		}
*/
		if (isStrict) {
			//snap = '.JLui-droppable';
			stopDrag = null;//endDragCursor;
			revert = 'invalid';
			dropElem = $cur.get(0);

			if (JlQ.inArray(tag, strictTags) == -1) {
				targetTags = '*:not('+strictCompTags.join(',')+')';
				isStrictComp = false;
			}
			else {
				targetTags = tag;
				isStrictComp = true;
			}
			//JlQ('*').droppable('destroy');

			//JlQ('*:not('+noDroppableTags+')').droppable('option', 'accept', $cur.selector);

			if (!addingMode) {
				staticClone = MGD.$lastCalled.clone().addClass('mg-whereto-element');
				cursorClone = MGD.$lastCalled.clone().addClass('mg-cursor-clone');
			}
		}
		else {
			//snap = false;
			stopDrag = stopDragCursor;
			revert = false;

			dropElem = null;

			cursorClone = $el.clone().addClass('mg-cursor-clone').removeAttr('m9t').cssImportant({top: '0px', left: '0px'});
		}

		elDepth = addingMode || !isStrictComp ? 9999 : $el.parents().length;

		if ($cur.hasClass('JLui-draggable')) {
			$cur.draggable('option', {
				revert: revert,
				stop: stopDrag
			});
		}
		else {
			$cur.draggable({
				handle: addingMode ? '#mg-cursor-handler' : null,
				/*
				snap: snap,
				snapMode: 'inner',
				*/
				scope: 'visual-elements',
				helper: helperFunction,
				revert: revert,
				start: startDragCursor,
				//drag: dragCursor,
				stop: stopDrag
			});
		}
	};

	that.enrichCursor = function () {

		var $cur = JlQ('#mg-cursor'),
			$curPanel = JlQ('#mg-cursor-panel', $cur).length ? JlQ('#mg-cursor-panel', $cur) : $cur;
			tag = MGD.lastCalled.tagName.toLowerCase(),
			addPanel = getToAddIcons($cur);

		$cur.addClass('mg-cursor-selected');

		JlQ('.mg-cursor-buttons').remove();

		if (tag != 'body') {

			that.initDragDrop($cur);

			if (addPanel) {
				JlQ('<div id="mg-cursor-edit" class="mg-images mg-images-black mg-cursor-buttons JLui-icon-pencil"></div>').click(dblClickCursor).appendTo($curPanel);
			}
		}
		$cur.resizable({
			ghost: true,
			alsoResize: MGD.$lastCalled,
			aspectRatio: MGOP.prefs.maintain_ratio == 'true',
			start: startResizeCursor,
			stop: stopResizeCursor
		});
		if (addPanel) {
			if (!JlQ('#mg-cursor-panel', $cur).length) {
				$cur.children().wrapAll('<div id="mg-cursor-panel" class="mg-add-removable">');
				JlQ('#mg-cursor-panel').click(MGP.clickCursorPanel);
			}
			else {
				JlQ('#mg-cursor-panel', $cur).removeClass('mg-cursor-small');
			}
			JlQ('#mg-cursor-patch').css(JlQ('#mg-cursor-panel').offset()).show();
		}
		else {
			JlQ('#mg-cursor-panel', $cur).addClass('mg-cursor-small');
			JlQ('#mg-cursor-edit, #mg-cursor-handler', $cur).remove();
			JlQ('#mg-cursor-patch').hide();
		}
		JlQ('#mg-cursor-layer').show();
	};

	that.pauperizeCursor = function () {

		var $cur = JlQ('#mg-cursor');

		$cur.removeClass('mg-cursor-selected');
		$cur.draggable('destroy');
		$cur.resizable('destroy');
		JlQ('#mg-cursor-panel').remove();
		JlQ('#mg-cursor-patch,#mg-cursor-layer').hide();
	};

	that.restoreElemDims = function ($el) {

		if (oldDim) {
			$el.width(oldDim.width);
			$el.height(oldDim.height);
		}
	};

	that.init = function () {

		strictTags = JlQ.merge(JlQ.merge([], strictCompTags), strictChildTags);

		makeDroppable(JlQ('*:not('+noDroppableTags+')'));

		JlQ('.mg-panel-quickedit').resizable({ 
			alsoResize: '#mg-quickedit textarea',
			start: function () {JlQ('#mg-quickedit textarea').css('overflow-y', 'auto')},
			stop: function () {JlQ('#mg-quickedit textarea').die('input paste').unbind('keyup')},
			minHeight: 50,
			minWidth: 80
		});

		JlQ('#mg-quickedit-save').click(saveQuickEdit);

		JlQ('.mg-menu-item-edit li').click(clickMenuEdit);
	};


	that.cancelQuickEdit = cancelQuickEdit;
	that.toggleEditMenu = toggleEditMenu;
	that.activateEditMenu = activateEditMenu;
	that.clearSelection = clearSelection;
	that.dblClickCursor = dblClickCursor;
	that.makeDroppable = makeDroppable;
};